package com.security03.filter;

import com.alibaba.fastjson.JSONArray;
import com.security03.bean.Users;
import com.security03.config.JwtConfig;
import com.security03.util.ResultCode;
import com.security03.util.ResultTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
public class LoginTokenFilter extends UsernamePasswordAuthenticationFilter {
    //相当于下一步包装的结果
    private AuthenticationManager authenticationManager;
    private RedisTemplate redisTemplate;

    public LoginTokenFilter(AuthenticationManager authenticationManager, RedisTemplate redisTemplate) {

        this.authenticationManager = authenticationManager;
        this.redisTemplate = redisTemplate;
        //关闭登录只允许post
        this.setPostOnly(false);
        //设置登录路径，并且post请求
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/user/login", "POST"));
    }

    /**
     * 用户登录
     *
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
        log.info("接收到的账号:{},密码:{}", userName, password);
        // 传递下去，登录接口 /user/login 调用请求时触发
        // UsernamePasswordAuthenticationToken 封装登录时传递来的数据信息
        // 交给 AuthenticationManager  进行登录认证校验
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName, password));
    }

    /**
     * 登录成功
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
      log.info("用户登录成功");
      //保存到redis中
        Users user= (Users) request.getAttribute("token");
        String token=JwtConfig.getJwtToken(user);
        redisTemplate.opsForValue().set("token:"+user.getId(),token);
        //返回登录成功相关信息
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out=response.getWriter();
        out.println(JSONArray.toJSONString(ResultTool.success(token)));
    }

    /**
     * 登录失败
     *
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
       //返回登录失败相关信息
        log.info("用户登录失败");
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out=response.getWriter();
        out.println(JSONArray.toJSONString(ResultTool.fail(ResultCode.COMMON_FAIL)));
    }
}
